using UnityEngine;
using System.Collections;
using System.Collections.Generic;
//-------------------------------------------------------------------------------------
//FSM Machine class manages the current state
//constructor takes a game object as parameter
//-------------------------------------------------------------------------------------
public class FSMMachine {
	
	public enum eFSMState {
	eStateIdle,
	eStatePatrol,
	eStateNone
	}
	
	private FSMState state;
	private eFSMState eState=eFSMState.eStateNone;
	protected GameObject m_obj;
	
	public FSMMachine(GameObject obj)
	{
		m_obj=obj;
		Debug.Log ("+++++constructor for FSMMachine class, attached to "+m_obj);
		//SetState(eFSMState.eStateIdle);
	}
	
	
	public void Update()
	{
		if (state!=null)
		{
			state.Update();
		}
	}
	
	
	public string GetState()
	{
		return eState.ToString();
	}
	
	
	public void SetState(eFSMState state_)
	{
		if (state_==eState) return;
		
		Debug.Log ("+++++attempting to set state "+ state_);
		eState=state_;
		
		switch(state_)
		{
		case eFSMState.eStateIdle:
			state=null;
			state=new FSMIdleState(m_obj);
			break;
			
		case eFSMState.eStatePatrol:
			state=null;
			state=new FSMPatrolState(m_obj);
			break;
		}//end switch
	}//end setstate
}//end class


//-------------------------------------------------------------------------------------
//base class for all states
//-------------------------------------------------------------------------------------
public class FSMState  {
	
	public GameObject m_obj;
	
	
	public FSMState(GameObject obj)
	{
		m_obj=obj;
		//Debug.Log ("constructor for FSMState class, attached to "+m_obj);
	}
	
	
	public virtual void Update()
	{
		//Debug.Log ("FSM:update");
		m_obj.transform.Translate (0.01f,0f,0f);
	}
}

//-------------------------------------------------------------------------------------
//patrol state inherits from FSMState
//note that Update function is overidden
//-------------------------------------------------------------------------------------
public class FSMPatrolState :FSMState {
	
	public List<Vector3> WaypointsList=new List<Vector3>();
	private int currentWaypoint=0;
	
	
	public FSMPatrolState(GameObject obj):base(obj)
	{
		
		Debug.Log ("+++++constructor for FSMPatrolState class, attached to "+m_obj);
		SetupWaypoints();
		
	}
	
	
	public void SetupWaypoints()
	{
		WaypointsList.Add(new Vector3(10.0f,0.0f,-10.0f));
		
		WaypointsList.Add(new Vector3(10.0f,0.0f,10.0f));
		WaypointsList.Add(new Vector3(-10.0f,0.0f,10.0f));
		WaypointsList.Add(new Vector3(-10.0f,0.0f,-10.0f));
		Debug.Log ("there are " + WaypointsList.Count + " waypoints");
	}
	
	
	~FSMPatrolState()
	{
		Debug.Log ("+++++destructor for FSMPatrolState class, attached to "+m_obj);
	}
	
	
	public override void Update()
	{
		float speed=0.1f;
		
		//calc direction to current waypoint
		Vector3 wp=WaypointsList[currentWaypoint];
		Vector3 dir=wp-m_obj.transform.position;
		//calc distance
		float distanceToWaypoint = dir.magnitude;
		//normalise
		dir.Normalize();
		
		//check if we have arrived
		if (distanceToWaypoint < 0.1)
		{
			//next waypoint
			currentWaypoint++;
			
			if (currentWaypoint >=WaypointsList.Count)
			{
				currentWaypoint=0;
			}
			Debug.Log ("now heading for waypoint: " + currentWaypoint);
		}
		//head to currentwaypoint 
		
		m_obj.transform.Translate (speed * dir);
	}
	
	
	
}

//-------------------------------------------------------------------------------------
//idle state inherits from FSMState base class
//overides update function
//-------------------------------------------------------------------------------------
public class FSMIdleState :FSMState {
	
	public FSMIdleState(GameObject obj):base(obj)
	{
		
		Debug.Log ("+++++constructor for FSMIdleState class, attached to "+m_obj);
		
	}
	
	
	public override void Update()
	{
		float a=-0.05f+0.1f*Random.value;
		float b=0.0f;
		float c=0.0f;
		
		m_obj.transform.Translate (a,b,c);
	}
	
}
